/*
-----------------------------------------------------------------------------
This source file is part of Labor3D
(Labor 3D Graphics Engine)

Copyright (c) 2009-2020 Rock Mao
* creator : Rock Mao
* created : 2009-9-20   22:29
* filename: LaborColor.h
-----------------------------------------------------------------------------
*/

#ifndef __LABORCOLOR_H__
#define __LABORCOLOR_H__
#include "../LaborCoreDef.h"

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#pragma pack(push,1)

NAMESPACE_LABOR3D_BEGIN


template <typename T> T _CLAM_TO_(T v , T a , T b)
{
	if( v < a ) return a ;
	if( v > b ) return b;
	return v;
}

template <typename T> T t_min(const T& v1 , const T& v2)
{
	return v1 < v2?v1:v2;
}

template <typename T> T t_max(const T& v1 , const T& v2)
{
	return v1 > v2?v1:v2;
}

class  LABORCORE_API CLColor_4ub;
class  LABORCORE_API CLColor_4f
{
public:
	float r,g,b,a;

	CLColor_4f()
	{
	}

	CLColor_4f(float _r, float _g,float _b,float _a)
	{
		r = _r; g = _g ; b = _b; a = _a;
	}

	CLColor_4f operator = (const CLColor_4ub& rhv);
	CLColor_4f(const CLColor_4ub& rhv);

	float fmax(float v1 , float v2)
	{
		if(v1 > v2) return v1;
		return v2;
	}

	float fmin(float v1 , float v2)
	{
		if(v1 < v2) return v1;
		return v2;
	}


	CLColor_4f  operator +(const CLColor_4f& rhv)
	{
		CLColor_4f outcl;
		outcl.r = fmin(1.0f,r + rhv.r);
		outcl.g = fmin(1.0f,g + rhv.g);
		outcl.b = fmin(1.0f,b + rhv.b);
		outcl.a = fmin(1.0f,a + rhv.a);
		return outcl;
	}

	CLColor_4f  operator -(const CLColor_4f& rhv)
	{
		CLColor_4f outcl;
		outcl.r = fmax(0.0f,r - rhv.r);
		outcl.g = fmax(0.0f,g - rhv.g);
		outcl.b = fmax(0.0f,b - rhv.b);
		outcl.a = fmax(0.0f,a - rhv.a);
		return outcl;
	}

	CLColor_4f& operator +=(const CLColor_4f& rhv)
	{
		r = fmin(1.0f,r + rhv.r);
		g = fmin(1.0f,g + rhv.g);
		b = fmin(1.0f,b + rhv.b);
		a = fmin(1.0f,a + rhv.a);
		return *this;
	}

	CLColor_4f& operator -=(const CLColor_4f& rhv)
	{
		r = fmax(0.0f,r - rhv.r);
		g = fmax(0.0f,g - rhv.g);
		b = fmax(0.0f,b - rhv.b);
		a = fmax(0.0f,a - rhv.a);
		return *this;
	}

	float abs()
	{
		return  (0.3f * r + 0.59f * g + 0.11f * b);
	}

};




class  LABORCORE_API CLColor_4ub
{
public:
	union
	{
		struct  {
			unsigned char b,g,r,a;
		};
		long color;
	};

	CLColor_4ub operator = (const CLColor_4f& rhv)
	{
		r = (unsigned char)(rhv.r * 255);
		g = (unsigned char)(rhv.g * 255);
		b = (unsigned char)(rhv.b * 255);
		a = (unsigned char)(rhv.a * 255);
		return * this;

	}
	CLColor_4ub(const CLColor_4f& rhv)
	{
		r = (unsigned char)(rhv.r * 255);
		g = (unsigned char)(rhv.g * 255);
		b = (unsigned char)(rhv.b * 255);
		a = (unsigned char)(rhv.a * 255);         
	}
#ifndef _MSC_VER


#endif
public:
	CLColor_4ub(){}
	CLColor_4ub(unsigned char _r,unsigned char _g , unsigned char _b,unsigned char _a = 255):r(_r),g(_g),b(_b),a(_a) {};
	CLColor_4ub(float _r,float _g , float _b , float _a)
	{
		r = unsigned char ( _CLAM_TO_(  _r , 0.0f, 1.0f) * 255 );
		g = unsigned char ( _CLAM_TO_(  _g , 0.0f, 1.0f) * 255 );
		b = unsigned char ( _CLAM_TO_(  _b , 0.0f, 1.0f) * 255 );
		a = unsigned char ( _CLAM_TO_(  _a , 0.0f, 1.0f) * 255 );
	}
	void        swapEndian()
	{
		unsigned char t = r;
		r = b;
		b = t;
	}

	CLColor_4ub  operator +(const CLColor_4ub& rhv)
	{
		CLColor_4ub outcl;
		outcl.r = t_min(255,r + int(rhv.r));
		outcl.g = t_min(255,g + int(rhv.g));
		outcl.b = t_min(255,b + int(rhv.b));
		outcl.a = t_min(255,a + int(rhv.a));
		return outcl;
	}

	CLColor_4ub  operator -(const CLColor_4ub& rhv)
	{
		CLColor_4ub outcl;
		outcl.r = t_max(0,r - int(rhv.r));
		outcl.g = t_max(0,g - int(rhv.g));
		outcl.b = t_max(0,b - int(rhv.b));
		outcl.a = t_max(0,a - int(rhv.a));
		return outcl;
	}

	CLColor_4ub& operator +=(const CLColor_4ub& rhv)
	{
		r = t_min(255,r + int(rhv.r));
		g = t_min(255,g + int(rhv.g));
		b = t_min(255,b + int(rhv.b));
		a = t_min(255,a + int(rhv.a));
		return *this;
	}

	CLColor_4ub& operator -=(const CLColor_4ub& rhv)
	{
		r = t_max(0,r - int(rhv.r));
		g = t_max(0,g - int(rhv.g));
		b = t_max(0,b - int(rhv.b));
		a = t_max(0,a - int(rhv.a));
		return *this;
	}

	unsigned char abs()
	{
		int n = int(0.3f * r + 0.59f * g + 0.11f * b);
		return n;
	}
};


inline CLColor_4f CLColor_4f::operator = (const CLColor_4ub& rhv)
{
	r = rhv.r /255.0f;
	g = rhv.g /255.0f;
	b = rhv.b /255.0f;
	a = rhv.a /255.0f;
	return *this;
}

inline CLColor_4f::CLColor_4f(const CLColor_4ub& rhv)
{
	r = rhv.r /255.0f;
	g = rhv.g /255.0f;
	b = rhv.b /255.0f;
	a = rhv.a /255.0f;     
}


#pragma pack(pop)

NAMESPACE_LABOR3D_END
#endif // __LABORCOLOR_H__

